/*
 *  Axolotl - Alternate persistence for Grails
 *  Copyright (C) 2008  Juanjo García Latre
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
package com.googlecode.axolotl.query;


/**
 * Abstract comparison between a property and a value.
 *
 *
 * @author     juanjo
 */
public abstract class PropertyComparison<T> extends Criterion {
	
	private PropertyName propertyName;
	private T value;


	/**
	 * 
	 */
	protected PropertyComparison() {
	}


	/**
	 * 
	 */
	protected PropertyComparison(String name, T value) {
		setProperty( new PropertyName(name) );
		setValue(value);
	}


	/**
	 *
	 */
	protected PropertyComparison(PropertyName propertyName, T value) {
		setProperty(propertyName);
		setValue(value);
	}


	/**
	 * Value is not cloned. It might not be cloneable and it doesn't seem
	 * a bad thing to share it between distinct criteria instances.
	 */
	public Object clone() {
		PropertyComparison<T> clon = (PropertyComparison<T>) super.clone();
		clon.propertyName = (PropertyName) this.propertyName.clone();
		clon.value = this.value;
		return clon;
	}


	/**
	 *
	 */
	public PropertyName getProperty() {
		return propertyName;
	}


	/**
	 * 
	 */
	public void setProperty(PropertyName propertyName) {
		this.propertyName = propertyName;
	}


	/**
	 *
	 */
	public T getValue() {
		return value;
	}


	/**
	 *
	 */
	public void setValue(T value) {
		this.value = value;
	}

	/*-------------------------------------------------------------------------*/ 

	/**
	 * 
	 */
	public boolean equals(Object obj) {
		if (obj == null || !(obj instanceof PropertyComparison)) {
			return false;
		}
		else {
			PropertyComparison that = (PropertyComparison) obj;
			return (that.propertyName == null ? this.propertyName == null : that.propertyName.equals(this.propertyName))
					&& equalsValue(that);
		}		
	}

	/*-------------------------------------------------------------------------*/ 

	/**
	 * Let concrete comparison types overwrite equality evaluation of values. 
	 */
	protected boolean equalsValue(PropertyComparison pc) {
		return pc.value == null ? this.value == null : pc.value.equals(this.value);
	}
}
